package com.g8.pethospitallearnbackend.service.impls;

import com.g8.pethospitallearnbackend.entity.*;
import com.g8.pethospitallearnbackend.exception.CustomException;
import com.g8.pethospitallearnbackend.mapper.DepartmentMapper;
import com.g8.pethospitallearnbackend.mapper.FlowMapper;
import com.g8.pethospitallearnbackend.mapper.OperationMapper;
import com.g8.pethospitallearnbackend.service.OperationService;
import com.g8.pethospitallearnbackend.utils.NewIdGenerateUtil;
import com.g8.pethospitallearnbackend.utils.responseUtil.ResponseStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class OperationServiceImpl implements OperationService {

    @Autowired
    private OperationMapper operationMapper;

    @Override
    public List<Operation> getOpsOfAFlow(String flowId) {
        OperationExample operationExample = new OperationExample();
        operationExample.setOrderByClause("op_order");
        operationExample.createCriteria().andFlowIdEqualTo(flowId);
        return operationMapper.selectByExample(operationExample);
    }

    @Override
    public List<Operation> getOpsByName(String opName) {
        OperationExample opExample = new OperationExample();
        opExample.createCriteria().andOpTitileLike("%" + opName + "%");
        List<Operation> ops = operationMapper.selectByExample(opExample);
        if (ops.isEmpty()) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到相关操作！");
        return ops;
    }

    @Override
    public Operation getAOperationById(String opId) {
        Operation op = operationMapper.selectByPrimaryKey(opId);
        if (op == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到该操作！");
        return op;
    }

    @Override
    public Operation addAOperation(Operation op) {
        if (!isValidFlowId(op.getFlowId()))
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "该flowId不存在");
        if (!op.getDepartId().isBlank())
            if (!isValidDepartId(op.getDepartId()))
                throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "该departId不存在");
        if (op.getOpTitile().isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "操作的名称不能为空！");
        // 随机生成id
        String id = NewIdGenerateUtil.getNumber(8);
        Operation repeat = operationMapper.selectByPrimaryKey(id);
        while(repeat != null) {
            id = NewIdGenerateUtil.getNumber(8);
            repeat = operationMapper.selectByPrimaryKey(id);
        }
        op.setOpId(id);
        // 注意实现一下排个序
        List<Operation> opsOfFlows = getOpsOfAFlow(op.getFlowId());
        if(!opsOfFlows.isEmpty()) {
            // 如果这个操作是插进去的，不是直接放到最后
            if(op.getOpOrder() <= opsOfFlows.size()) {
                // 把后面的操作都往后挪一位
                for(int i = op.getOpOrder()-1; i < opsOfFlows.size(); i++){
                    Operation o = opsOfFlows.get(i);
                    if (o.getOpOrder() < op.getOpOrder()) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR, "排序标的序号有问题");
                    o.setOpOrder(o.getOpOrder()+1);
                    operationMapper.updateByPrimaryKey(o);
                }
            } // 如果放最后，直接设置一下序号，免得有跳着标序号的问题
            else op.setOpOrder(opsOfFlows.size() + 1);
        } else op.setOpOrder(1); // 如果该流程中没有操作
        operationMapper.insert(op);
        return operationMapper.selectByPrimaryKey(id);
    }

    @Override
    public Operation modifyOperation(Operation op) {
        Operation opDB = operationMapper.selectByPrimaryKey(op.getOpId());
        if (opDB == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到相关操作！");
        // 校验一下
        if (!isValidFlowId(op.getFlowId()))
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "该flowId不存在");
        if (!op.getDepartId().isBlank())
            if (!isValidDepartId(op.getDepartId()))
                throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "该departId不存在");
        if (op.getOpTitile().isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "操作的名称不能为空！");
        // 如果还在原来的流程
        if (op.getFlowId().equals(opDB.getFlowId())) {
            // 注意实现一下排个序
            List<Operation> opsOfFlows = getOpsOfAFlow(op.getFlowId());
            // 如果这个操作顺序改变了，重新排序
            // 如果这个操作跳到了前面去，把两个序号之间的order都+1
            if(op.getOpOrder() < opDB.getOpOrder()) {
                if (op.getOpOrder() < 1) op.setOpOrder(1);
                for(int i = op.getOpOrder()-1; i < opDB.getOpOrder()-1; i++) {
                    Operation o = opsOfFlows.get(i);
                    o.setOpOrder(o.getOpOrder()+1);
                    operationMapper.updateByPrimaryKey(o);
                }
            } // 如果跳到了后面去，把两个序号之间的order都-1
            else if (op.getOpOrder() > opDB.getOpOrder()) {
                // 如果直接跳到最后的后面去了，那么设为最后一个
                if (op.getOpOrder() > opsOfFlows.size()) op.setOpOrder(opsOfFlows.size());
                for(int i = opDB.getOpOrder(); i < op.getOpOrder(); i++) {
                    Operation o = opsOfFlows.get(i);
                    o.setOpOrder(o.getOpOrder()-1);
                    operationMapper.updateByPrimaryKey(o);
                }
            }
            // 然后更新
            operationMapper.updateByPrimaryKey(op);
        } // 如果改流程了
        else {
            // 原来的流程中后面顺序都往前走一下
            List<Operation> opsOfOriginalFlows = getOpsOfAFlow(opDB.getFlowId());
            for(int i = opDB.getOpOrder(); i < opsOfOriginalFlows.size(); i++) {
                Operation o = opsOfOriginalFlows.get(i);
                o.setOpOrder(o.getOpOrder()-1);
                operationMapper.updateByPrimaryKey(o);
            }
            // 删除原来的
            operationMapper.deleteByPrimaryKey(opDB.getOpId());
            // 相当于新流程中加了个操作
            // 注意实现一下排个序
            List<Operation> opsOfFlowsAfter = getOpsOfAFlow(op.getFlowId());
            if(!opsOfFlowsAfter.isEmpty()) {
                // 如果这个操作是插进去的，不是直接放到最后
                if(op.getOpOrder() <= opsOfFlowsAfter.size()) {
                    // 把后面的操作都往后挪一位
                    for(int i = op.getOpOrder()-1; i < opsOfFlowsAfter.size(); i++){
                        Operation o = opsOfFlowsAfter.get(i);
                        if (o.getOpOrder() < op.getOpOrder()) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR, "排序标的序号有问题");
                        o.setOpOrder(o.getOpOrder()+1);
                        operationMapper.updateByPrimaryKey(o);
                    }
                } // 如果放最后，直接设置一下序号，免得有跳着标序号的问题
                else op.setOpOrder(opsOfFlowsAfter.size() + 1);
            } else op.setOpOrder(1); // 如果该流程中没有操作
            // 再插入
            operationMapper.insert(op);
        }

        return this.getAOperationById(op.getOpId());
    }

    @Override
    public String deleteAOp(String opId) {
        Operation op = operationMapper.selectByPrimaryKey(opId);
        if (op == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST);
        // 流程中后面顺序都往前走一下
        List<Operation> opsOfOriginalFlows = getOpsOfAFlow(op.getFlowId());
        for(int i = op.getOpOrder(); i < opsOfOriginalFlows.size(); i++) {
            Operation o = opsOfOriginalFlows.get(i);
            o.setOpOrder(o.getOpOrder()-1);
            operationMapper.updateByPrimaryKey(o);
        }
        // 删除该操作
        if (operationMapper.deleteByPrimaryKey(opId) == 1) return "删除成功";
        throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR, "删除不成功");
    }

    @Override
    public String modifyOpOrderInBulk(OperaOrderChangeInBulk bulk) {
        if (bulk == null) throw new CustomException(ResponseStatusEnum.MISS_PARAM);
        String flowId = bulk.getFlowId();
        int count = 0;
        if (flowMapper.selectByPrimaryKey(flowId) == null)
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到该流程");
        List<String> orderedIds = bulk.getAllOpIds();
        if (this.getOpsOfAFlow(flowId).size() != orderedIds.size())
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "提供的该流程操作不全！");
        StringBuffer msg = new StringBuffer();
        for (int i = 0; i < orderedIds.size(); i++) {
            String opId = orderedIds.get(i);
            Operation op = this.getAOperationById(opId);
            if (op == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到操作"+opId);
            if (!op.getFlowId().equals(flowId))
                throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "操作"+opId+"不是流程"+flowId+"的操作！");
            op.setOpOrder(i+1);
            if (operationMapper.updateByPrimaryKey(op) < 1)
                msg.append("操作").append(opId).append("更新失败\n");
            else count++;
        }
        if (count == orderedIds.size()) msg.append("操作顺序修改成功");
        return msg.toString();
    }


    @Autowired
    private FlowMapper flowMapper;

    /**
     * 校验一下这个flowId合法吗，在数据库中存在吗
     * @param flowId
     * @return
     */
    public boolean isValidFlowId(String flowId) {
        if (flowId.isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "该操作属于的流程flowId缺失！");
        if (flowMapper.selectByPrimaryKey(flowId) != null) return true;
        return false;
    }

    @Autowired
    private DepartmentMapper departmentMapper;

    /**
     * 校验一下这个departId合法吗，在数据库中存在吗
     * @param departId
     * @return
     */
    public boolean isValidDepartId(String departId) {
        if (departId.isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "该操作属于的科室departId缺失！");
        if (departmentMapper.selectByPrimaryKey(departId) != null) return true;
        return false;
    }

}
